<!-- 找到的穿梭框组件不支持移动端，尝试着写一个 -->
<template>
	<view class="transfer">
		<!-- 左侧穿梭框 -->
		<view class="left">
			<u-checkbox-group v-model="leftChkValue" placement="column" @change="leftChkChange">
				<u-checkbox :name="-1" :checked="leftAllChkStatus" :label="titles.length == 2 ? titles[0] : '列表1'"
					labelSize="18px" labelColor="#303133"></u-checkbox>


				<view v-for="(item,index) in leftList" :key="index">

					<view class="weui-flexcen">
						<!-- name就是选中的值 -->
						<u-checkbox :name="item[keyName]" :checked="item.checked" :label="item[labelName]"
							:disabled="item[disabledName]"></u-checkbox>
					</view>
				</view>
			</u-checkbox-group>
		</view>
		<!-- 中间操作按钮 -->
		<view class="center">
			<u-row>
				<u-col span="6">
					<u-button icon="arrow-left" size="mini" @click="toLeft"></u-button>
				</u-col>
				<u-col span="6">
					<u-button icon="arrow-right" size="mini" @click="toRight"></u-button>
				</u-col>
			</u-row>
		</view>
		<!-- 右侧穿梭框 -->
		<view class="right">
			<u-checkbox-group v-model="rightChkValue" placement="column" @change="rightChkChange">
				<u-checkbox :name="-2" :checked="rightAllChkStatus" :label="titles.length == 2 ? titles[1] : '列表2'"
					labelSize="18px" labelColor="#303133"></u-checkbox>
				<view v-for="(item,index) in rightList" :key="index">
					<view class="weui-flexcen" style="color: #666666;font-size:24rpx;">
						<!-- name就是选中的值 -->
						<u-checkbox :name="item[keyName]" :checked="item.checked" :label="item[labelName]"></u-checkbox>
					</view>
				</view>
			</u-checkbox-group>
		</view>
	</view>
</template>

<!-- 
	组件属性对应element-ui中的el-transfer组件，使用方式和其完全一致，但是有些属性没有完成功能。
	目前已完成功能的属性：
	v-model：绑定使用此方式，不要使用value传值
	data：功能与el-transfer一致
	titles：功能与el-transfer一致
	props：功能与el-transfer一致

	已完成功能的事件：
	change：功能与el-transfer一致
	left-check-change：功能与el-transfer一致
	right-check-change：功能与el-transfer一致

 -->
<script>
	export default {
		// 微信小程序解除样式隔离
		// #ifdef MP-WEIXIN
		options: {
			styleIsolation: "shared"
		},
		// #endif
		name: "PyTransfer",
		props: {
			data: {
				type: Array,
				default() {
					return [];
				}
			},
			titles: {
				type: Array,
				default() {
					return [];
				}
			},
			value: {
				type: Array,
				default() {
					return [];
				}
			},
			props: {
				type: Object,
				default() {
					return {
						label: 'label',
						key: 'key',
						disabled: 'disabled'
					};
				}
			}
		},
		data() {
			return {
				leftList: [],
				rightList: [],
				// 右侧key值列表
				rightKeyList: this.value,
				//左边列表
				filterLeftSortList: this.data,
				leftChkValue: [],//左边选中的数据
				rightChkValue: [],//右边选中的数据
				//右边列表
				filterRightSortList: [],
				leftAllChkStatus: false,
				rightAllChkStatus: false,
				filterLeftSort: "",//左侧搜索框
				filterRightSort: "",//右侧搜索框
				// 复选框key名称
				keyName: this.props.key,
				// 复选框Label名称
				labelName: this.props.label,
				// 复选框Disabled名称
				disabledName: this.props.disabled,
				// 是否重置
				hasReset: false
			};
		},
		created() {
			//暂存一份原始数据用来备份
			this.leftList = this.filterLeftSortList;
			this.rightList = this.filterRightSortList;

			// 如果表单有值，设置初值
			let rightKeyList = this.rightKeyList;


			if (rightKeyList && rightKeyList.length && rightKeyList.length > 0) {
				let propsKey = this.keyName;
				let propsDisabled = this.disabledName;
				let toRightList = []
				this.leftList.forEach(currentLeft => {
					let currentKeyValue = currentLeft[propsKey];
					let currentDisabled = currentLeft[propsDisabled];
					if (rightKeyList.includes(currentKeyValue) && !currentDisabled) {
						toRightList.push(currentLeft);
					}
				});
				this.rightList = this.rightList.concat(toRightList);
				const newLeft = this.leftList.filter((s) => !toRightList.includes(s))
				this.leftList = newLeft;
			}

		},
		watch: {
			rightList: function (newVal, oldVal) {
				let keyName = this.keyName;
				let newKeyList = newVal.map(item => item[keyName]);
				this.rightKeyList = newKeyList;

				// 充值表单时，不向父组件传值，避免形成循环
				if (!this.hasReset) {
					this.$emit("input", newKeyList);
				} else {
					this.hasReset = false;
				}


				// 发生变化的数组
				let changeList = [];
				if (newVal.length > oldVal.length) {
					changeList = newVal.filter(item => !oldVal.includes(item));
				} else {
					changeList = oldVal.filter(item => !newVal.includes(item));
				}
				this.$emit("change", changeList);


			},

			value: function (newVal, oldVal) {
				// 表单重置时调用
				if (newVal && newVal.length == 0) {

					this.leftList = this.filterLeftSortList;
					this.hasReset = true;
					this.rightKeyList = [];
					this.rightList = [];
					this.rightAllChkStatus = false;
					this.leftAllChkStatus = false;

					this.$nextTick(() => {
						this.leftList.forEach((item, index) => {
							if (item.checked) {
								this.$set(this.leftList, index, { ...item, checked: false });
							}
						});
					});
				} else {
					this.hasReset = false;
				}
			}

		},
		methods: {
			toLeft() {
				//到左边
				//拿到右边选中的数据
				let selectRight = this.rightList.filter((s) => s.checked);
				if (selectRight.length == 0) {
					//未选中
					return;
				}

				// 重置默认选择
				this.leftChkValue = [];
				this.leftAllChkStatus = false;
				this.rightAllChkStatus = false;

				// 将选择框重置
				selectRight.map(item => item.checked = false);

				//把选中的数据放到leftList中
				this.leftList = this.leftList.concat(selectRight);

				//把选中的数据从rightList移除
				const newLeft = this.rightList.filter((s) => !selectRight.includes(s))
				this.rightList = newLeft;
			},
			toRight() {
				//到右边
				//拿到左边选中的数据
				let selectLeft = this.leftList.filter((s) => s.checked);
				
				if (selectLeft.length == 0) {
					//未选中
					return;
				}

				// 重置默认选择
				this.rightChkValue = [];
				this.leftAllChkStatus = false;
				this.rightAllChkStatus = false;

				// 将选择框重置
				selectLeft.map(item => item.checked = false);

				this.rightList = this.rightList.concat(selectLeft);

				//把选中的数据从leftList移除
				const newLeft = this.leftList.filter((s) => !selectLeft.includes(s))
				this.leftList = newLeft;
			},
			filterLeftSortValue(v) {
				//输入框数据改变事件
				this.leftList = this.filterLeftSortList.filter((s) => s.initialism.startsWith(v));
			},
			filterRightSortValue(v) {
				//输入框数据改变事件
				this.rightList = this.filterRightSortList.filter((s) => s.initialism.startsWith(v));
			},
			leftChkChange(e) {
				// 没有被禁用的列表
				let notDisabledList = this.leftList.filter(item => !item[this.disabledName]);
				// 计算改变的列表
				let changeList = [];
				if (e.includes(-1) && !this.leftAllChkStatus) {
					changeList = notDisabledList.filter(item => !item.checked);
				} else if (e.includes(-1) && this.leftAllChkStatus) {
					changeList = notDisabledList.filter(item => !e.includes(item[this.keyName]))
				} else if (this.leftAllChkStatus && notDisabledList.length == e.length) {
					changeList = notDisabledList;
				} else {
					// 由未选中状态变为选中状态列表
					let toChecked = notDisabledList.filter(item => !item.checked && e.includes(item[this.keyName]));
					//由选中状态变未未选中状态列表
					let toUnchecked = notDisabledList.filter(item => item.checked && !e.includes(item[this.keyName]));

					// 发生改变的数组
					changeList = toChecked.concat(toUnchecked);
				}

				//如果不是全选，则取消全选按钮的勾选
				//全选：点全选 || 选中所有
				if (((e.includes(-1)) || (e.length == notDisabledList.length)) && this.leftAllChkStatus == false) {
					//左边全选
					this.leftList.forEach(item => {
						if (!item[this.disabledName]) {
							item.checked = true;
						}
					});
					this.leftAllChkStatus = true;
				} else {
					this.leftAllChkStatus = false;
					//取消全选
					this.leftList.forEach(item => {
						item.checked = false;
					});
					if (e.includes(-1)) {
						//全选状态下取消其中一个
						e.forEach(c => {
							this.leftList.forEach(item => {
								if (c == item[this.keyName] && !item[this.disabledName]) {
									item.checked = true;
								}
							})
						});
					} else if (!e.includes(-1) && e.length < notDisabledList.length) {
						//逐个取消全选
						e.forEach(c => {
							this.leftList.forEach(item => {
								if (c == item[this.keyName] && !item[this.disabledName]) {
									item.checked = true;
								}
							})
						});
					}
				}

				//当前被选中的列表
				let currentCheckedList = this.leftList.filter(item => item.checked);
				this.$emit("left-check-change", currentCheckedList, changeList);
			},
			rightChkChange(e) {
				let rightList = this.rightList;
				// 计算改变的列表
				let changeList = [];
				if (e.includes(-2) && !this.rightAllChkStatus) {
					changeList = rightList.filter(item => !item.checked);
				} else if (e.includes(-2) && this.rightAllChkStatus) {
					changeList = rightList.filter(item => !e.includes(item[this.keyName]))
				} else if (this.rightAllChkStatus && rightList.length == e.length) {
					changeList = rightList;
				} else {
					// 由未选中状态变为选中状态列表
					let toChecked = rightList.filter(item => !item.checked && e.includes(item[this.keyName]));
					//由选中状态变未未选中状态列表
					let toUnchecked = rightList.filter(item => item.checked && !e.includes(item[this.keyName]));

					// 发生改变的数组
					changeList = toChecked.concat(toUnchecked);
				}

				//全选：点全选 || 选中所有
				if (((e.includes(-2)) || (e.length == this.rightList.length)) && this.rightAllChkStatus == false) {
					//右边全选
					this.rightList.forEach(item => {
						item.checked = true;
					});
					this.rightAllChkStatus = true;
				} else {
					this.rightAllChkStatus = false;
					//取消全选
					this.rightList.forEach(item => {
						item.checked = false;
					});
					if (e.includes(-2)) {
						//全选状态下取消其中一个
						e.forEach(c => {
							this.rightList.forEach(item => {
								if (c == item[this.keyName] && !item[this.disabledName]) {
									item.checked = true;
								}
							})
						});
					} else if (!e.includes(-2) && e.length < this.rightList.length) {
						//逐个取消全选
						e.forEach(c => {
							this.rightList.forEach(item => {
								if (c == item[this.keyName] && !item[this.disabledName]) {
									item.checked = true;
									// this.$set(item, "checked", true);
									// console.log(c+' 被选中')
								}
							})
						});
					}
				}

				//当前被选中的列表
				let currentCheckedList = this.rightList.filter(item => item.checked);
				this.$emit("right-check-change", currentCheckedList, changeList);

			}
		}
	}
</script>

<style scoped>
	.transfer {
		display: flex;
		justify-content: center;
		align-items: center;
	}

	.left {
		margin: 50rpx 30rpx 80rpx 0;
	}

	.right {
		margin: 50rpx 0 80rpx 40rpx;
	}

	/deep/ .u-checkbox {
		margin-bottom: 10rpx;
	}
</style>